#include "json.h"
#include "json_private.h"

char mapping[128][2] =
    {
        {'n', '\n'},
        {'t', '\t'},
        {'\"', '\"'},
        {'\\', '\\'},
        {0, 0}};
int mapSize = 0;

void getMapSize()
{
    int i = 0;
    while (mapping[i][0] != 0)
    {
        i++;
    }
    mapSize = i;
}

char getMap(char in)
{
    for (int i = 0; i < mapSize; i++)
    {
        if (mapping[i][0] == in)
        {
            return mapping[i][1];
        }
    }
    return 0;
}

int JSON_VAR::getVal(const string &in, int start, int *rei)
{
    checkMapSize;
    int size = in.size();
    //* 字符串类型
    if (in[start] == '\"')
    {
        type = JSON_TSTR;

        JSON_STR *str = new JSON_STR();
        //* 读取字符串
        for (int i = start + 1; i < size; i++)
        {
            if (in[i] == '\"')
            {
                *rei = i + 1;
                break;
            }
            else
            {
                (*str) += in[i];
            }
        }

        //* 替换转义字
        int slen = str->size();
        for (int i = 0; i < slen; i++)
        {
            if ((*str)[i] == '\\')
            {
                (*str)[i] = getMap(((*str)[i + 1]));
                str->erase(i + 1, 1);
                slen--;
            }
        }
        p = str;
    }
    //* 布尔类型 true
    else if (in[start] == 't')
    {
        if (in.substr(start, 4) == VTRUE)
        {
            type = JSON_TBOOL;
            p = new JSON_BOOL(true);
            *rei = start + 4;
        }
    }
    //* 布尔类型 false
    else if (in[start] == 'f')
    {
        if (in.substr(start, 5) == VFALSE)
        {
            type = JSON_TBOOL;
            p = new JSON_BOOL(false);
            *rei = start + 5;
        }
    }
    //* 数字类型
    else if (in[start] >= '0' && in[start] <= '9')
    {
        type = JSON_TNUM;
        JSON_NUM *nums = new JSON_NUM(0);
        bool dot = 0;
        // 在小数点之前
        for (int i = start; i < size; i++)
        {
            if (in[i] == ',' || in[i] == '}')
            {
                *rei = i;
                break;
            }
            else if (in[i] == '.')
            {
                start = i + 1;
                dot = 1;
                break;
            }
            else
            {
                *nums = *nums * 10 + (in[i] - '0');
            }
        }

        if (dot)
        {
            // 小数点后
            JSON_NUM curl = 0.1;
            for (int i = start; i < size; i++)
            {
                if (in[i] == ',' || in[i] == '}')
                {
                    *rei = i;
                    break;
                }
                else
                {
                    *nums += curl * (in[i] - '0');
                    curl *= 0.1;
                }
            }
        }
        p = nums;
    }
    else if (in[start] == '[')
    {
        type = JSON_TARR;
        p = new JSON_ARR();
        JSON_ARR *nums = (JSON_ARR *)p;

        JSON_VAR cur;
        for (int i = start + 1; i < size; i++)
        {
            if (in[i] == ',')
            {
                continue;
            }
            if (in[i] == ']')
            {
                break;
            }
            else
            {
                cur.init();
                cur.getVal(in, i, &i);
                nums->push_back(cur);
                if (in[i] == ',')
                {
                    continue;
                }
                if (in[i] == ']')
                {
                    *rei = i + 1;
                    break;
                }
            }
        }
    }
    else if (in[start] == '{')
    {
        type = JSON_TOBJ;
        p = new JSON_OBJ();
        JSON_OBJ *obj = (JSON_OBJ *)p;

        obj->load(in, start, rei);
    }
    return type;
}

void JSON_VAR::del()
{
    name = "";
    if (type == JSON_TNUM)
    {
        JSON_NUM *ptr = (JSON_NUM *)p;
        delete ptr;
    }
    else if (type == JSON_TBOOL)
    {
        JSON_BOOL *ptr = (JSON_BOOL *)p;
        delete ptr;
    }
    else if (type == JSON_TSTR)
    {
        JSON_STR *ptr = (JSON_STR *)p;
        delete ptr;
    }
    else if (type == JSON_TARR)
    {
        JSON_ARR *ptr = (JSON_ARR *)p;
        delete ptr;
    }
    else if (type == JSON_TOBJ)
    {
        JSON_OBJ *ptr = (JSON_OBJ *)p;
        delete ptr;
    }
    p = NULL;
    type = JSON_TNIL;
}

void JSON_VAR::init()
{
    p = NULL;
    name = "";
    type = JSON_TNIL;
}